import Dataset from '../dataset'
import Geojson from '../geojson'
import utils from '../utils'
import Geom from '../geom'

function exportTopoJSON(dataset, opts) {
  const extension = '.' + (opts.extension || 'json')
  const needCopy = !opts.final || Dataset.datasetHasPaths(dataset) && dataset.arcs.getRetainedInterval() > 0
  let stringify = JSON.stringify

  if (needCopy) {
    dataset = Dataset.copyDatasetForExport(dataset);
  }

  if (opts.prettify) {
    stringify = Geojson.getFormattedStringify('coordinates,arcs,bbox,translate,scale'.split(','))
  }

  if (opts.width > 0 || opts.height > 0) {
    opts = utils.defaults({invert_y: true}, opts)
    Geom.transformDatasetToPixels(dataset, opts)
  }

  if (opts.precision) {
    Geom.setCoordinatePrecision(dataset, opts.precision)
  }

  if (opts.singles) {
    return Dataset.splitDataset(dataset).map(function(dataset) {
      return {
        content: stringify(TopoJSON.exportTopology(dataset, opts)),
        filename: (dataset.layers[0].name || 'output') + extension
      }
    })
  } else {
    return [{
      filename: opts.file || utils.getOutputFileBase(dataset) + extension,
      content: stringify(TopoJSON.exportTopology(dataset, opts))
    }];
  }
}
// Convert a dataset object to a TopoJSON topology object
// Careful -- arcs must be a copy if further processing will occur.
function exportTopology(dataset, opts) {
  const topology = {type: "Topology", arcs: []}
  const hasPaths = Dataset.datasetHasPaths(dataset)
  const bounds = Dataset.getDatasetBounds(dataset)

  if (opts.bbox && bounds.hasBounds()) {
    topology.bbox = bounds.toArray()
  }

  if (hasPaths && opts.presimplify && !dataset.arcs.getVertexData().zz) {
    // Calculate simplification thresholds if needed
    api.simplify(dataset, opts)
  }
  // auto-detect quantization if arcs are present
  if (!opts.no_quantization && (opts.quantization || hasPaths)) {
    topology.transform = TopoJSON.transformDataset(dataset, bounds, opts)
  }
  if (hasPaths) {
    internal.dissolveArcs(dataset) // dissolve/prune arcs for more compact output
    topology.arcs = TopoJSON.exportArcs(dataset.arcs, bounds, opts)
    if (topology.transform) {
      TopoJSON.deltaEncodeArcs(topology.arcs)
    }
  }

  // export layers as TopoJSON named objects
  topology.objects = dataset.layers.reduce(function(objects, lyr, i) {
    const name = lyr.name || "layer" + (i + 1)
    objects[name] = TopoJSON.exportLayer(lyr, dataset.arcs, opts)
    return objects
  }, {})

  // retain crs data if relevant
  internal.exportCRS(dataset, topology);
  if (opts.metadata) {
    topology.metadata = internal.exportMetadata(dataset)
  }
  return topology
}
export default {
  exportTopoJSON,
}